package com.yc.thread.pro3_bestMatching;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * @author zwei
 * @create 2024-07-25 11:43
 */
public class BestMatchingConcurrentCalculation {
    public static BestMatchingData getBestMatchingWords(String word, List<String>dictionary) throws InterruptedException, ExecutionException {
        BestMatchingData result=new BestMatchingData();
        //1.任务数
        int numthread=Runtime.getRuntime().availableProcessors();   //获取CPU的核数
        ThreadPoolExecutor executor= (ThreadPoolExecutor) Executors.newFixedThreadPool(numthread);  //按cpu核数创建线程池
        CountDownLatch countDownLatch=new CountDownLatch(numthread);   //计数器 确保所有任务执行完再继续
        //2.计算每个任务对应的词汇量  startIndex endIndex
        int size=dictionary.size();
        int step=size/numthread;
        int startIndex=0;
        int endIndex=step;
        //3.创建任务  BestMatchingTask
        List<BestMatchingTask>tasks=new ArrayList<>();
        List<Future<BestMatchingData>>lisFuture=new ArrayList<>();
        for (int i=0;i<numthread;i++){
            startIndex=i*step;
            if (i==numthread-1){
                endIndex=size;
            }else {
                endIndex=startIndex+step;
            }
//            BestMatchingTask task=new BestMatchingTask(dictionary,word,startIndex,endIndex);
            BestMatchingTask task=new BestMatchingTask(dictionary,word,startIndex,endIndex,countDownLatch);
            tasks.add(task);
            Future<BestMatchingData>future=executor.submit(task);
            lisFuture.add(future);
        }
        //4.将上面创建的BestMatchingTask提交给线程池
        //invokeAll()方法一次性所有任务后，只有所有的任务都执行完了，才会继续往下走
//        List<Future<BestMatchingData>>lisFuture=executor.invokeAll(tasks);

        countDownLatch.await();    //等待所有任务完成
        System.out.println("如果任务没有完成，invokeAll()方法会阻塞");
        executor.shutdown();    //因为任务完成了  所以关闭执行器
        //5.通过FutureTask.get()获取以上任务的执行结果  BestMatchingData,汇总(找最小距离对应的词汇)
        int minDistance=Integer.MAX_VALUE;
        List<String>words=new ArrayList<>();    //最短距离对应的单词
        for (Future<BestMatchingData> future:lisFuture){
            BestMatchingData bestMatchingData=future.get();
            if (bestMatchingData.getDistance()<minDistance){
                words.clear();
                minDistance= bestMatchingData.getDistance();
                words.addAll(bestMatchingData.getWords());
            } else if (bestMatchingData.getDistance()==minDistance) {
                //这个任务找到最短距离  与已知的一样 则合并单词列表
                words.addAll(bestMatchingData.getWords());
            }
        }
        //6.包装成BestMatchingData
        result.setDistance(minDistance);
        result.setWords(words);

        //7.返回
        return result;
    }
}
